package com.tao.utilslib.log.autoClear;

import android.os.Build;

import androidx.annotation.RequiresApi;

import com.tao.utils.TimeSimpleUtil;
import com.tao.utilslib.data.Obj;
import com.tao.utilslib.file.FileUtil;
import com.tao.utilslib.log.LogUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class LogAutoClear {
    private ExecutorService executorService;
    long checkTime = TimeUnit.HOURS.toMillis(1);
    long vaildTime = TimeUnit.DAYS.toMillis(30);
    Set<String> paths = new HashSet<>();
    private Future<?> future;
    static LogAutoClear autoClear = new LogAutoClear();
    int deleteType = 1;

    public void setCheckTime(long checkTime, TimeUnit unit) {
        this.checkTime = unit.toMillis(checkTime);
    }

    public void setVaildTime(long vaildTime, TimeUnit unit) {
        this.vaildTime = unit.toMillis(vaildTime);
    }

    public void setDeleteType(int deleteType) {
        this.deleteType = deleteType;
    }

    public static LogAutoClear getInstance() {
        return autoClear;
    }

    private LogAutoClear() {
        createPool();
    }

    public void start() {
        createPool();
        cancel();
        future = executorService.submit(new CheckdTask());
    }

    private void createPool() {
        if (Obj.isNULL(executorService) || executorService.isShutdown() || executorService.isTerminated()) {
            executorService = Executors.newSingleThreadExecutor();
        }
    }

    public void cancel() {
        if (!(Obj.isNULL(future) || future.isCancelled() || future.isDone())) {
            future.cancel(true);
        }
        future = null;
    }

    public void release() {
        cancel();
        if (Obj.notNULL(executorService) && !executorService.isShutdown() && !executorService.isTerminated()) {
            executorService.shutdownNow();
        }
        executorService = null;
    }

    public boolean isVlidFile(File file) {
        long creationTimeByAndroid = FileUtil.getCreationTimeByAndroid(file);

//        try {
//            LogUtil.e("isVlidFile " + file.getAbsolutePath() + "  creationTimeByAndroid " + TimeSimpleUtil.timeStamp2Date(creationTimeByAndroid)+" current " +TimeSimpleUtil.TimeNowWithFormat()+"   vaildTime:" +vaildTime);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        return (System.currentTimeMillis() - creationTimeByAndroid < vaildTime);
    }

    AutoAddPathCall autoAddPathCall ;

    public void setAutoAddPathCall(AutoAddPathCall autoAddPathCall) {
        this.autoAddPathCall = autoAddPathCall;
    }

    private void autoAddFolder() {
        if (Obj.notNULL(autoAddPathCall)){
            List<String> paths = autoAddPathCall.onAdd();
            if (Obj.notNULL(paths)){
                for (String path : paths) {
                    addPath(path);
                }
            }
        }
        
    }


    private class CheckdTask implements Runnable {
        @Override
        public void run() {
            try {
                while (true) {
                    autoAddFolder();
                    checkedFiles(paths);
                    Thread.sleep(checkTime);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void checkedFiles(Collection<String> paths) {
        List<String> myList = new ArrayList<>();

        myList.addAll(paths);
        for (String path : myList) {
            File file = new File(path);
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (null != files)
                    for (File file1 : files) {
                        checkFile(file1);
                    }
            } else {
                checkFile(file);
            }
        }
    }

    /**
     * 文件删除方案
     * 1. 循环删除文件夹内过期文件  文件夹为空时才删除文件夹
     * 2. 文件夹过期时直接删除文件夹内所有文件
     *
     * @param file
     */
    private void checkFile(File file) {
//        LogUtil.e("checkFile " + file.getAbsolutePath());

        if (!file.exists())
            return;
        if (file.isDirectory()) {
            if (deleteType > 0) {
                deleteUnVlidFolder(file);
            } else {
                File[] files = file.listFiles();
                if (files != null) {
                    for (File file1 : files) {
                        checkFile(file1);
                    }
                }
                deleteOfEmptyFolder(file);
            }
        } else {
            deleteOfVaildTime(file);
        }

    }

    private void deleteUnVlidFolder(File file) {
        if (isVlidFile(file)) return;
//        LogUtil.e("deleteUnVlidFolder " + file.getAbsolutePath());

        System.err.println("deleteUnVlidFolder " + file.getAbsolutePath());
        FileUtil.deleteParintFile(file, true);
    }

    private void deleteOfEmptyFolder(File file) {
        File[] files1 = file.listFiles();
        if ((files1 == null || files1.length == 0) && !isVlidFile(file)) {
            System.err.println("deleteOfEmptyFolder " + file.getAbsolutePath());
            LogUtil.e("deleteOfEmptyFolder " + file.getAbsolutePath());

            FileUtil.deleteChildFile(file);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void deleteOfVaildTime(File file) {
  
        if (!isVlidFile(file)) {
            System.err.println("delete_valid_file " + file.getAbsolutePath());
            LogUtil.e("delete_valid_file " + file.getAbsolutePath());
            FileUtil.deleteChildFile(file);
        }
    }

    public static void main(String[] args) {
        LogAutoClear autoClear = LogAutoClear.getInstance();
        autoClear.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        autoClear.addPath("C:\\Users\\Administrator\\Desktop\\test");

//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        autoClear.cancel();
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        autoClear.release();
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        autoClear.start();
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        autoClear.clearPath();

        TimeUnit days = TimeUnit.DAYS;
        int nt = 1;
        System.err.println(days.toHours(nt));
        System.err.println(days.toMinutes(nt));
        System.err.println(days.toSeconds(nt));
        System.err.println(days.toMillis(nt));
        System.err.println(days.toNanos(nt));
    }

    public void clearPath() {
        if (Obj.notNULL(paths))
            paths.clear();
    }

    public void addPath(String path) {
        LogUtil.e("addPath " + path);
        if (paths.contains(path)) return;
        if (paths != null && Obj.notNULL(path))
            paths.add(path);
    }

    public void removePath(String path) {
        if (paths != null && Obj.notNULL(path))
            paths.remove(path);
    }
    
    public  interface AutoAddPathCall {
        List<String> onAdd();
    }
}
